<?php
class template{
	public $striping=true;
	public $cache_dir='';
	public $caching=false;
	public $cache_lifetime=10;
	public $cache_file='';
	public $cache_ext='.html';
	public $cache_tpl=false;
	public $reset_publics = TRUE;
	public $reset_vars=true;
	public $ldelim = '{';
	public $rdelim = '}';
	public $BAldelim = '{';
	public $BArdelim = '}';
	public $EAldelim = '{/';
	public $EArdelim = '}';
	public $resultHTML="";
	public $scalars = array();
	public $arrays  = array();
	public $carrays = array();
	public $ifs     = array();
	public function __construct(){
		parent::__construct();
		$this->cache_dir=$this->yum->vars('sys','tpl').'cache/';
	}
	function set($tag,$var,$if = NULL){
		if(is_array($var)){
			$this->arrays[$tag] = $var;
			if($if){
				$result = $var ? TRUE : FALSE;
				$this->ifs[] = $tag;
				$this->scalars[$tag] = $result;
			}
		}else{
			$this->scalars[$tag] = $var;
			if($if) $this->ifs[] = $tag;
		}
	}
	function set_cloop($tag, $array, $cases){
		$this->carrays[$tag] = array(
			'array' => $array,
			'cases' => $cases);
	}
	function reset_vars($scalars, $arrays, $carrays, $ifs) {
		if($scalars) $this->scalars = array();
		if($arrays)  $this->arrays  = array();
		if($carrays) $this->carrays = array();
		if($ifs)     $this->ifs     = array();
	}
	function get_tags($tag, $directive){
		$tags['b'] = $this->BAldelim . $directive . $tag . $this->BArdelim;
		$tags['e'] = $this->EAldelim . $directive . $tag . $this->EArdelim;
		return $tags;
	}
	function get_tag($tag){
		return $this->ldelim . '$' . $tag . $this->rdelim;
	}
	function get_statement($t, &$contents) {
		$tag_length = strlen($t['b']);
		$fpos = strpos($contents, $t['b']) + $tag_length;
		$lpos = strpos($contents, $t['e']);
		$length = $lpos - $fpos;
		return substr($contents, $fpos, $length);
	}
	function parse($contents){
		if(!empty($this->ifs)){
			foreach($this->ifs as $value) {
				$contents = $this->parse_if($value, $contents);
			}
		}
		foreach($this->scalars as $key => $value) {
			$contents = str_replace($this->get_tag($key), $value, $contents);
		}
		foreach($this->arrays as $key => $array){
			$contents = $this->parse_loop($key, $array, $contents);
		}
		foreach($this->carrays as $key => $array) {
			$contents = $this->parse_cloop($key, $array, $contents);
		}
		if($this->reset_vars) $this->reset_vars(FALSE, TRUE, TRUE, FALSE);
		return $contents;
	}
	function parse_if($tag, $contents){
		$t = $this->get_tags($tag, 'if:');
		$entire_statement = $this->get_statement($t, $contents);
		$tags['b'] = NULL;
		$tags['e'] = $this->BAldelim . 'else:' . $tag . $this->BArdelim;
		if(($else = strpos($entire_statement, $tags['e']))){
			$if = $this->get_statement($tags, $entire_statement);
			$else = substr($entire_statement, $else + strlen($tags['e']));
		}else{
			$else = NULL;
			$if = $entire_statement;
		}
		$this->scalars[$tag] ? $replace = $if : $replace = $else;
		return str_replace($t['b'] . $entire_statement . $t['e'], $replace, $contents);
	}
	function parse_loop($tag, $array, $contents){
		$t = $this->get_tags($tag, 'loop:');
		$loop = $this->get_statement($t, $contents);
		$parsed = NULL;
		foreach($array as $key=>$value){
			if(is_numeric($key) && is_array($value)){
				$i = $loop;
				foreach($value as $key2=>$value2){
					if(!is_array($value2)){
						$i = str_replace($this->get_tag($tag . '[].'.$key2), $value2, $i);
					}else {
						$i = $this->parse_loop($tag.'[].' . $key2, $value2, $i);
					}
				}
			}elseif(is_string($key) && !is_array($value)) {
				$contents = str_replace($this->get_tag($tag.'.'.$key),$value,$contents);
			}elseif(!is_array($value)){
				$i = str_replace($this->get_tag($tag.'[]'), $value, $loop);
			}
			if(isset($i)) $parsed .= rtrim($i);
		}
		return str_replace($t['b'] . $loop . $t['e'], $parsed, $contents);
	}
	function parse_cloop($tag,$array,$contents){
		$t = $this->get_tags($tag, 'cloop:');
		$loop = $this->get_statement($t, $contents);
		$array['cases'][] = 'default';
		$case_content = array();
		$parsed = NULL;
		foreach($array['cases'] as $case){
			$ctags[$case] = $this->get_tags($case, 'case:');
			$case_content[$case] = $this->get_statement($ctags[$case], $loop);
		}
		foreach($array['array'] as $key => $value){
			if(is_numeric($key) && is_array($value)){
				if(isset($value['case'])) $current_case = $value['case'];
				else $current_case = 'default';
				unset($value['case']);
				$i = $case_content[$current_case];
				foreach($value as $key2 => $value2) {
					$i = str_replace($this->get_tag($tag . '[].' . $key2), $value2, $i);
				}
			}
			$parsed .= rtrim($i);
		}
		return str_replace($t['b'] . $loop . $t['e'], $parsed, $contents);
	}
	function _getCacheFile($file_name,$cache_id=null){
		$md5_string=md5($file_name);
		if(!file_exists($this->cache_dir)){
			if(!mkdir($this->cache_dir,0740)){
				$this->error($this->cache_dir.' not found!');
			}
		}
		$this->cache_file=$this->cache_dir.$md5_string.($cache_id!=null?"id[$cache_id]":"").$this->cache_ext;
	}
	function cache($file_name,$cache_id=null){
		$this->_getCacheFile($file_name,$cache_id);
		$tpl_ini="{cache_id:".($cache_id==null?"null":$cache_id).",template:\"$file_name\",expires:".($this->yum->runtime+$this->cache_lifetime)."}";
		$this->_writeToFile($this->cache_file,$tpl_ini.$this->resultHTML);
	}
	function is_cached($file_name,$cache_id=null){
		if(!$this->cache_tpl){
			if(!$this->caching){return false;}
			$this->_getCacheFile($file_name,$cache_id);
			if (!file_exists($this->cache_file)){return false;}
			$now=$this->yum->runtime;
	        $orig=filemtime($this->cache_file);
	        $chk = $now-$orig;
	        if ($chk>=($this->cache_lifetime)){return false;}
	        $this->cache_tpl=true;
		}
        return true;
	}
	function cache_file($file_name,$cache_id=null){
		if($this->is_cached($file_name,$cache_id)){
			$content=file_get_contents($this->cache_file);
			echo substr_replace($content,"",0,strpos($content,"}")+1);
			return true;
		}else{
			return false;
		}
	}
	function _writeToFile($file,$content,$mode='w'){
        $oldmask = umask(0);
        $fp = fopen($file, $mode);
        if (!$fp) return false;
        @fwrite($fp,$content);
        @fclose($fp);
        @umask($oldmask);
        return true;
    }
    function strip(){
   		return $this->resultHTML=preg_replace('![\t ]*[\r\n]+[\t ]*!','',$this->resultHTML);
    }
	function fetch($file_name,$cache_id=null){
		$file = $this->TPLPATH.$file_name;
		$fp = fopen($file,'rb');
		if(!$fp) return FALSE;
		$contents = fread($fp, filesize($file));
		fclose($fp);
		$this->resultHTML=$this->parse($contents);
		if($this->striping){$this->strip();}
		if($this->caching){$this->cache($file_name,$cache_id);}
		return $this->resultHTML;
	}
	function display($file_name,$cache_id=null){
		$HTML="";
		if($this->caching){
			if(!$this->cache_file($file_name,$cache_id)){
				$HTML=$this->fetch($file_name,$cache_id);
			}
		}else{
			$HTML=$this->fetch($file_name,$cache_id);
		}
		echo $HTML;
	}
}
?>